package gold.gold05;

import java.util.Deque;
import java.util.LinkedList;

/**
 * 正则表达式, deque, 字符串匹配
 * 栈来做计算
 */
public class S1626计算器 {
    public static void main(String[] args) {
        // 42318
        System.out.println(calculate("3+2*2-7-1-324+23/3 + 323*132"));
    }

    /**
     * 5,
     * 注意这个split的东西, 如果头有, 那么结果array第一个元素会是空字符串, "abc" split("a") => [, bc], 就有一个空的
     */
    public static int calculate(String s) {
        String cacuString = new String(s);
        cacuString = cacuString.replaceAll(" ", ""); // replaceAll是删除元素的好办法
        // 注意转义要加两个, -需要转义
        String[] nums = cacuString.split("[/+\\-*\\/]");
        // 匹配一串连续的数字只能这样
        String[] opes = cacuString.split("[0-9]+");
        int totalLen = nums.length;
        Deque<String> cacuStack = new LinkedList<>();
        cacuStack.addLast(nums[0]);
        int numsCount = 1;
        int opesCount = 1;
        while(numsCount < totalLen && opesCount < totalLen){
            String curOpe = opes[opesCount++];
            String curNum = nums[numsCount++];
            if(curOpe.equals("*") || curOpe.equals("/")){
                String preNum = cacuStack.pollLast();
                cacuStack.addLast(cacu(preNum, curNum, curOpe));
            }else{
                cacuStack.addLast(curOpe);
                cacuStack.addLast(curNum);
            }
        }
        String res = cacuStack.poll();
        while(cacuStack.size() != 0){
            String ope = cacuStack.pollFirst();
            String num = cacuStack.pollFirst();
            res = cacu(res, num, ope);
        }
        return Integer.parseInt(res);
    }
    public static String cacu(String num1, String num2, String ope){
        int res = -1; // 初始化好习惯
        switch(ope){
            // 注意如果res直接在case语句里面return的话, break会变unreachable错误
            case "+":
                res =  Integer.parseInt(num1) + Integer.parseInt(num2);
                break;
            case "-":
                res =  Integer.parseInt(num1) - Integer.parseInt(num2);
                break;

            case "*":
                res =  Integer.parseInt(num1) * Integer.parseInt(num2);
                break;

            case "/":
                res = Integer.parseInt(num1) / Integer.parseInt(num2);
                break;
            default:
        }
        return res + "";
    }

    /**
     * 别人的, 我那个正则表达式还是太浮夸了
     */
    public int calculate2(String s) {
        int num = 0, index = 0, length = s.length();
        if(s.length() == 0) return 0;

        // 因为没有括号,所以最多只要存储两个中间值就可
        Integer number1 = null, number2 = null;
        // ope记录最新的符号,若为+-,则记录' ',否则记录'*'或'/'
        char ope = ' ';
        // 记录+-,将+-表达为一个数的正负,最后都相加即可
        boolean flag = true;

        while(index < length) {
            char c = s.charAt(index);
            if('0' <= c && c <= '9') {
                num = c - '0';
                while(index + 1 < length && '0' <= (c = s.charAt(index + 1)) && c <= '9') {
                    num = num * 10 + c - '0';
                    ++index;
                }
                if(ope == '*' || ope == '/') {
                    if(number2 != null) {
                        number2 = ope == '*' ? number2 * num : number2 / num;
                    } else {
                        number1 = ope == '*' ? number1 * num : number1 / num;
                    }
                    ope = ' '; // reset ope

                } else {
                    if(number1 == null) number1 = flag ? num : -num;
                    else {
                        // number2合并入number1,并将最新值给number2
                        number1 += number2 == null ? 0 : number2;
                        number2 = flag ? num : -num;
                    }
                    flag = true; // reset flag, the default is a positive number
                }

            } else if(c != ' ') {
                if(c == '*' || c == '/') {
                    ope = c; // record when c is '*' or '/'
                } else if(c == '-') {
                    flag = false; // set 'false' when operator is '-'
                }
            }
            index++;
        }

        return number2 == null ? number1 : number1 + number2;
    }


}
